"""
事件装饰器 - 提供便捷的事件处理和发布装饰器
支持自动注册、条件处理、重试机制等
"""

import functools
import inspect
import asyncio
from typing import (
    Callable, Union, List, Optional, Any, Type, Dict,
    TypeVar, Generic, get_type_hints
)
from dataclasses import dataclass
from enum import Enum

from .bus import (
    Event, EventBus, EventPriority, IEventHandler
)
from ..logging.manager import get_logger

F = TypeVar('F', bound=Callable[..., Any])

class RetryPolicy(Enum):
    """重试策略"""
    NONE = "none"
    FIXED = "fixed"
    EXPONENTIAL = "exponential"
    LINEAR = "linear"

@dataclass
class RetryConfig:
    """重试配置"""
    policy: RetryPolicy = RetryPolicy.NONE
    max_attempts: int = 3
    delay: float = 1.0
    max_delay: float = 60.0
    backoff_factor: float = 2.0
    exceptions: tuple = (Exception,)

class EventHandlerMeta(type):
    """事件处理器元类 - 自动注册装饰的方法"""
    
    def __new__(mcs, name, bases, attrs, **kwargs):
        cls = super().__new__(mcs, name, bases, attrs)
        
        # 收集事件处理方法
        handlers = []
        for attr_name, attr_value in attrs.items():
            if hasattr(attr_value, '_event_handler_config'):
                handlers.append((attr_name, attr_value._event_handler_config))
        
        cls._event_handlers = handlers
        return cls

def event_handler(
    event_types: Union[str, List[str]],
    priority: EventPriority = EventPriority.NORMAL,
    condition: Optional[Callable[[Event], bool]] = None,
    retry_config: Optional[RetryConfig] = None,
    bus_name: str = "default",
    auto_register: bool = False,  # 🔥 修复：默认禁用自动注册，避免导入时副作用
    event_bus: Optional['EventBus'] = None  # 新增：支持依赖注入
):
    """
    事件处理器装饰器
    
    ⚠️  重要变更：默认不再自动注册，避免导入时副作用！
    
    Args:
        event_types: 要处理的事件类型
        priority: 处理优先级
        condition: 处理条件函数
        retry_config: 重试配置
        bus_name: 事件总线名称（当event_bus为None时使用）
        auto_register: 是否自动注册到事件总线（默认False，避免导入时副作用）
        event_bus: 可选的事件总线实例，支持依赖注入模式
        
    推荐用法：
        # 1. 装饰函数但不自动注册（推荐）
        @event_handler("user.created")
        def handle_user_created(event):
            pass
            
        # 2. 在应用启动时显式注册
        bus = container.get(EventBus)
        register_decorated_handlers(my_handlers_module, bus)
        
        # 3. 或者使用依赖注入（最佳实践）
        @event_handler("user.created", event_bus=injected_bus)
        def handle_user_created(event):
            pass
            
    已弃用用法：
        # ❌ 不推荐：导入时自动注册（隐蔽副作用）
        @event_handler("user.created", auto_register=True)
        def handle_user_created(event):
            pass
    """
    def decorator(func: F) -> F:
        # 保存配置信息
        func._event_handler_config = {
            'event_types': event_types if isinstance(event_types, list) else [event_types],
            'priority': priority,
            'condition': condition,
            'retry_config': retry_config,
            'bus_name': bus_name,
            'auto_register': auto_register,
            'original_func': func
        }
        
        # 如果是异步函数，创建异步包装器
        if inspect.iscoroutinefunction(func):
            @functools.wraps(func)
            async def async_wrapper(event: Event):
                return await _handle_event_with_retry(func, event, retry_config)
        else:
            @functools.wraps(func)
            def sync_wrapper(event: Event):
                return _handle_event_with_retry(func, event, retry_config)
        
        wrapper = async_wrapper if inspect.iscoroutinefunction(func) else sync_wrapper
        wrapper._event_handler_config = func._event_handler_config
        
        # 🔥 修复：智能注册逻辑
        # 1. 如果提供了event_bus，自动注册（依赖注入模式，安全）
        # 2. 如果没有event_bus但auto_register=True，使用全局总线（已弃用）
        if event_bus is not None:
            # 依赖注入模式：自动注册到提供的事件总线（推荐且安全）
            bus = event_bus
            registration_id = bus.subscribe(
                event_types=event_types,
                handler=wrapper,
                priority=priority,
                filter_func=condition
            )
            wrapper._registration_id = registration_id
        elif auto_register:
            # 全局总线模式已被完全移除
            raise RuntimeError(
                "❌ auto_register=True is no longer supported because global event bus has been removed. "
                "Use dependency injection instead:\n"
                "  • Pass event_bus parameter: @event_handler('event', event_bus=injected_bus)\n"
                "  • Or use explicit registration: register_decorated_handlers(module, event_bus)\n"
                "See EVENT_BUS_MIGRATION_GUIDE.md for complete migration instructions."
            )
        
        return wrapper
    
    return decorator

def event_publisher(
    event_type: str,
    data_mapper: Optional[Callable[..., Any]] = None,
    condition: Optional[Callable[..., bool]] = None,
    priority: EventPriority = EventPriority.NORMAL,
    bus_name: str = "default",
    async_publish: bool = False,
    event_bus: Optional['EventBus'] = None  # 新增：支持依赖注入
):
    """
    事件发布装饰器 - 在函数执行后自动发布事件
    
    Args:
        event_type: 要发布的事件类型
        data_mapper: 数据映射函数，将函数参数/返回值转换为事件数据
        condition: 发布条件函数
        priority: 事件优先级
        bus_name: 事件总线名称（当event_bus为None时使用）
        async_publish: 是否异步发布事件
        event_bus: 可选的事件总线实例，支持依赖注入模式
        
    注意：
        - 如果提供了event_bus参数，将使用该实例而不是全局总线
        - 推荐在新代码中使用event_bus参数以避免全局状态问题
    """
    def decorator(func: F) -> F:
        if inspect.iscoroutinefunction(func):
            @functools.wraps(func)
            async def async_wrapper(*args, **kwargs):
                result = await func(*args, **kwargs)
                
                # 检查发布条件
                if condition and not condition(*args, **kwargs):
                    return result
                
                # 准备事件数据
                event_data = result
                if data_mapper:
                    event_data = data_mapper(*args, result=result, **kwargs)
                
                # 发布事件
                event = Event(
                    event_type=event_type,
                    data=event_data,
                    priority=priority,
                    metadata={
                        'function': func.__name__,
                        'module': func.__module__,
                        'args': str(args),
                        'kwargs': str(kwargs)
                    }
                )
                
                # 选择事件总线实例
                if event_bus is not None:
                    bus = event_bus
                else:
                    import warnings
                    warnings.warn(
                        "Using global event bus in @event_publisher is deprecated. "
                        "Pass event_bus parameter instead for better testability.",
                        DeprecationWarning,
                        stacklevel=2
                    )
                    bus = get_event_bus(bus_name)
                
                if async_publish:
                    await bus.publish_async(event)
                else:
                    bus.publish(event)
                
                return result
        else:
            @functools.wraps(func)
            def sync_wrapper(*args, **kwargs):
                result = func(*args, **kwargs)
                
                # 检查发布条件
                if condition and not condition(*args, **kwargs):
                    return result
                
                # 准备事件数据
                event_data = result
                if data_mapper:
                    event_data = data_mapper(*args, result=result, **kwargs)
                
                # 发布事件
                event = Event(
                    event_type=event_type,
                    data=event_data,
                    priority=priority,
                    metadata={
                        'function': func.__name__,
                        'module': func.__module__,
                        'args': str(args),
                        'kwargs': str(kwargs)
                    }
                )
                
                # 选择事件总线实例
                if event_bus is not None:
                    bus = event_bus
                else:
                    import warnings
                    warnings.warn(
                        "Using global event bus in @event_publisher is deprecated. "
                        "Pass event_bus parameter instead for better testability.",
                        DeprecationWarning,
                        stacklevel=2
                    )
                    bus = get_event_bus(bus_name)
                
                bus.publish(event)
                
                return result
        
        wrapper = async_wrapper if inspect.iscoroutinefunction(func) else sync_wrapper
        wrapper._event_publisher_config = {
            'event_type': event_type,
            'data_mapper': data_mapper,
            'condition': condition,
            'priority': priority,
            'bus_name': bus_name,
            'async_publish': async_publish
        }
        
        return wrapper
    
    return decorator

def listen_for(*event_types: str, **kwargs):
    """监听事件的简化装饰器"""
    return event_handler(list(event_types), **kwargs)

def publish_on(event_type: str, **kwargs):
    """发布事件的简化装饰器"""
    return event_publisher(event_type, **kwargs)

def async_event_handler(
    event_types: Union[str, List[str]],
    priority: EventPriority = EventPriority.NORMAL,
    condition: Optional[Callable[[Event], bool]] = None,
    retry_config: Optional[RetryConfig] = None,
    bus_name: str = "default",
    auto_register: bool = False  # 🔥 修复：默认禁用自动注册
):
    """
    异步事件处理器装饰器（event_handler的别名，为了明确表示异步）
    
    这是event_handler的别名，因为event_handler已经自动支持异步函数
    """
    return event_handler(
        event_types=event_types,
        priority=priority,
        condition=condition,
        retry_config=retry_config,
        bus_name=bus_name,
        auto_register=auto_register
    )

def _handle_event_with_retry(func: Callable, event: Event, retry_config: Optional[RetryConfig]):
    """带重试机制的事件处理"""
    if not retry_config or retry_config.policy == RetryPolicy.NONE:
        return func(event)
    
    logger = get_logger("event_handler")
    last_exception = None
    
    for attempt in range(retry_config.max_attempts):
        try:
            return func(event)
        except retry_config.exceptions as e:
            last_exception = e
            
            if attempt < retry_config.max_attempts - 1:
                delay = _calculate_retry_delay(retry_config, attempt)
                logger.warning(
                    f"Event handler failed, retrying in {delay}s",
                    event_type=event.event_type,
                    event_id=event.event_id,
                    attempt=attempt + 1,
                    max_attempts=retry_config.max_attempts,
                    error=str(e)
                )
                
                if inspect.iscoroutinefunction(func):
                    import asyncio
                    asyncio.sleep(delay)
                else:
                    import time
                    time.sleep(delay)
            else:
                logger.error(
                    f"Event handler failed after {retry_config.max_attempts} attempts",
                    event_type=event.event_type,
                    event_id=event.event_id,
                    error=str(e),
                    exc_info=e
                )
    
    raise last_exception

def _calculate_retry_delay(config: RetryConfig, attempt: int) -> float:
    """计算重试延迟"""
    if config.policy == RetryPolicy.FIXED:
        return config.delay
    elif config.policy == RetryPolicy.LINEAR:
        return min(config.delay * (attempt + 1), config.max_delay)
    elif config.policy == RetryPolicy.EXPONENTIAL:
        return min(config.delay * (config.backoff_factor ** attempt), config.max_delay)
    else:
        return config.delay

class EventHandlerRegistry:
    """事件处理器注册表 - 管理类级别的事件处理器"""
    
    def __init__(self):
        self._registrations: Dict[str, List[str]] = {}
        self.logger = get_logger("event_registry")
    
    def register_class(self, cls: Type, instance: Any = None, bus_name: str = "default"):
        """注册类中的所有事件处理器"""
        if not hasattr(cls, '_event_handlers'):
            return []
        
        registrations = []
        bus = get_event_bus(bus_name)
        
        for method_name, config in cls._event_handlers:
            if instance:
                handler = getattr(instance, method_name)
            else:
                # 静态方法或类方法
                handler = getattr(cls, method_name)
            
            registration_id = bus.subscribe(
                event_types=config['event_types'],
                handler=handler,
                priority=config['priority'],
                filter_func=config['condition']
            )
            
            registrations.append(registration_id)
            
            self.logger.info(
                f"Registered class event handler: {cls.__name__}.{method_name}",
                event_types=config['event_types'],
                priority=config['priority'].name
            )
        
        class_key = f"{cls.__module__}.{cls.__name__}"
        self._registrations[class_key] = registrations
        
        return registrations
    
    def unregister_class(self, cls: Type, bus_name: str = "default"):
        """注销类中的所有事件处理器"""
        class_key = f"{cls.__module__}.{cls.__name__}"
        
        if class_key not in self._registrations:
            return False
        
        bus = get_event_bus(bus_name)
        registrations = self._registrations[class_key]
        
        for registration_id in registrations:
            bus.unsubscribe(registration_id)
        
        del self._registrations[class_key]
        
        self.logger.info(f"Unregistered class event handlers: {cls.__name__}")
        return True

# 🔥 修复：移除全局注册表实例，改为工厂函数
def create_event_handler_registry() -> EventHandlerRegistry:
    """创建事件处理器注册表实例（工厂函数）"""
    return EventHandlerRegistry()

def register_event_handlers(
    cls: Type, 
    instance: Any = None, 
    bus_name: str = "default",
    registry: Optional[EventHandlerRegistry] = None
):
    """
    注册类事件处理器的便捷函数
    
    Args:
        cls: 要注册的类
        instance: 类实例（如果是实例方法）
        bus_name: 事件总线名称
        registry: 可选的注册表实例，如果不提供则创建新的
    """
    if registry is None:
        registry = create_event_handler_registry()
    return registry.register_class(cls, instance, bus_name)

def unregister_event_handlers(
    cls: Type, 
    bus_name: str = "default",
    registry: Optional[EventHandlerRegistry] = None
):
    """
    注销类事件处理器的便捷函数
    
    Args:
        cls: 要注销的类
        bus_name: 事件总线名称  
        registry: 可选的注册表实例，如果不提供则创建新的
    """
    if registry is None:
        registry = create_event_handler_registry()
    return registry.unregister_class(cls, bus_name)

def register_decorated_handlers(
    module_or_functions,
    event_bus: 'EventBus',
    registry: Optional[EventHandlerRegistry] = None
) -> List[str]:
    """
    显式注册装饰的事件处理器
    
    这是推荐的注册方式，避免了导入时的隐蔽副作用
    
    Args:
        module_or_functions: 模块对象或函数列表
        event_bus: 事件总线实例
        registry: 可选的注册表实例
        
    Returns:
        注册ID列表
        
    Example:
        # 在应用启动时显式注册
        import my_handlers
        bus = container.get(EventBus)
        register_decorated_handlers(my_handlers, bus)
    """
    if registry is None:
        registry = create_event_handler_registry()
        
    registrations = []
    
    if hasattr(module_or_functions, '__dict__'):
        # 处理模块
        functions = [
            getattr(module_or_functions, name) 
            for name in dir(module_or_functions)
            if callable(getattr(module_or_functions, name)) and 
               hasattr(getattr(module_or_functions, name), '_event_handler_config')
        ]
    else:
        # 处理函数列表
        functions = module_or_functions
    
    for func in functions:
        if hasattr(func, '_event_handler_config'):
            config = func._event_handler_config
            registration_id = event_bus.subscribe(
                event_types=config['event_types'],
                handler=func,
                priority=config['priority'],
                filter_func=config['condition']
            )
            registrations.append(registration_id)
            
    return registrations

# 示例使用 - 展示新的最佳实践
if __name__ == "__main__":
    from .bus import EventBus
    
    # ✅ 推荐方式1：装饰但不自动注册，然后显式注册
    @event_handler("user.created", priority=EventPriority.HIGH)
    def on_user_created(event: Event):
        print(f"用户创建: {event.data}")
    
    @event_handler(["user.updated", "user.deleted"])
    async def on_user_changed(event: Event):
        print(f"用户变更: {event.event_type} - {event.data}")
    
    # ✅ 推荐方式2：使用依赖注入的事件总线
    event_bus = EventBus()  # 通常从容器获取
    
    @event_handler("payment.process", event_bus=event_bus)
    def process_payment_with_di(event: Event):
        print(f"处理支付（依赖注入）: {event.data}")
    
    # ✅ 显式注册所有装饰的处理器
    import sys
    current_module = sys.modules[__name__]
    registrations = register_decorated_handlers(current_module, event_bus)
    print(f"注册了 {len(registrations)} 个事件处理器")
    
    # ✅ 推荐的类处理器用法
    class UserService(metaclass=EventHandlerMeta):
        
        @event_handler("user.register")  # 不自动注册
        def handle_user_register(self, event: Event):
            print(f"处理用户注册: {event.data}")
        
        @event_handler("user.login", priority=EventPriority.HIGH)
        async def handle_user_login(self, event: Event):
            print(f"处理用户登录: {event.data}")
    
    # 显式注册类处理器
    user_service = UserService()
    registry = create_event_handler_registry()
    register_event_handlers(UserService, user_service, registry=registry)
    
    # ❌ 已弃用：导入时自动注册（会显示警告）
    # @event_handler("deprecated.event", auto_register=True)
    # def deprecated_handler(event: Event):
    #     pass  # 这会在导入时立即注册，产生副作用
